#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>

static cv::Rect _bounding_rectangle(const std::vector<cv::Point>& pts) {
    cv::Rect rect;
    int minX = -1, maxX = -1, minY = -1, maxY = -1;
    for (int i = 0; i < pts.size(); i++) {
        int x = pts[i].x;
        int y = pts[i].y;
        if (minX == -1 || minX > x) {
            minX = x;
        }
        if (maxX == -1 || maxX < x) {
            maxX = x;
        }
        if (minY == -1 || minY > y) {
            minY = y;
        }
        if (maxY == -1 || maxY < y) {
            maxY = y;
        }
    }
    rect.x = minX;
    rect.y = minY;
    rect.width = maxX - minX + 1;
    rect.height = maxY - minY + 1;
    return rect;
}

int main(int argc, char **argv) {
    cv::Mat src = cv::imread("/home/xlll/Downloads/opencv/samples/data/lena.jpg", cv::IMREAD_COLOR);
    if (src.empty()) {
        std::cout << "failed to read image" << std::endl;
        return EXIT_FAILURE;
    }
    cv::Mat binary;
    cv::Canny(src, binary, 100, 200);
    
    std::vector<std::vector<cv::Point>> contours;
    cv::findContours(binary, contours, cv::RETR_LIST, cv::CHAIN_APPROX_NONE);
    std::vector<cv::Rect> rects;
    for (int i = 0; i < contours.size(); i++) {
        rects.push_back(cv::boundingRect(contours[i]));
    }
    cv::RNG rng(100);
    for (int i = 0; i < rects.size(); i++) {
        std::cout << "No." << i << ": " << rects[i] << std::endl;
        cv::rectangle(src, rects[i], cv::Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)));
    }
    
    std::vector<cv::Rect> rects2;
    for (int i = 0; i < contours.size(); i++) {
        rects2.push_back(_bounding_rectangle(contours[i]));
    }
    bool result_same = true;
    if (rects.size() != rects2.size()) {
        result_same = false;
    }
    if (result_same) {
        for (int i = 0; i < rects.size(); i++) {
            cv::Rect rect1, rect2;
            rect1 = rects[i];
            rect2 = rects2[i];
            if (rect1.x != rect2.x || rect1.y != rect2.y || rect1.width != rect2.width || rect1.height != rect2.height) {
                result_same = false;
                break;
            }
        }
    }
    std::cout << (result_same ? "Results are the same!" : "Results are not the same!") << std::endl;
    
    cv::imshow("src", src);
    cv::imshow("binary", binary);
    cv::waitKey(0);
    
    return 0;
}
